/**
 * 
 */
package gsm.cable.server.datastore;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;

import com.google.appengine.api.datastore.AsyncDatastoreService;
import com.google.appengine.api.datastore.DatastoreAttributes;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreService.KeyRangeState;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyRange;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Transaction;

/**
 * @author G.S.M
 * 
 */
public class DataService {

	private static AsyncDatastoreService asyncDatastoreService;

	private static DatastoreService datastoreService;

	private static ThreadLocal<List<Transaction>> activeTransaction;

	private static ThreadLocal<List<Future<Transaction>>> activeAsyncTransaction;

	static {
		asyncDatastoreService = DatastoreServiceFactory.getAsyncDatastoreService();
		datastoreService = DatastoreServiceFactory.getDatastoreService();
		activeTransaction = new ThreadLocal<List<Transaction>>();
		activeAsyncTransaction = new ThreadLocal<List<Future<Transaction>>>();
	}

	public static KeyRangeState allocateIdRange(KeyRange range) {
		return datastoreService.allocateIdRange(range);
	}

	public static KeyRange allocateIds(String kind, long num) {
		return datastoreService.allocateIds(kind, num);
	}

	public static KeyRange allocateIds(Key parent, String kind, long num) {
		return datastoreService.allocateIds(parent, kind, num);
	}

	public static void delete(Key... keys) {
		Transaction transaction = datastoreService.beginTransaction();
		List<Transaction> list = activeTransaction.get();
		if (list == null) {
			list = Collections.synchronizedList(new ArrayList<Transaction>());
		}
		list.add(transaction);
		datastoreService.delete(keys);
	}

	public static void delete(Iterable<Key> keys) {
		Transaction transaction = datastoreService.beginTransaction();
		List<Transaction> list = activeTransaction.get();
		if (list == null) {
			list = Collections.synchronizedList(new ArrayList<Transaction>());
		}
		list.add(transaction);
		datastoreService.delete(keys);
	}

	public static Entity get(Key key) throws EntityNotFoundException {
		Transaction transaction = datastoreService.beginTransaction();
		List<Transaction> list = activeTransaction.get();
		if (list == null) {
			list = Collections.synchronizedList(new ArrayList<Transaction>());
		}
		list.add(transaction);
		return datastoreService.get(key);
	}

	public static Map<Key, Entity> get(Iterable<Key> keys) {
		Transaction transaction = datastoreService.beginTransaction();
		List<Transaction> list = activeTransaction.get();
		if (list == null) {
			list = Collections.synchronizedList(new ArrayList<Transaction>());
		}
		list.add(transaction);
		return datastoreService.get(keys);
	}

	public static PreparedQuery prepare(Query query) {
		Transaction transaction = datastoreService.beginTransaction();
		List<Transaction> list = activeTransaction.get();
		if (list == null) {
			list = Collections.synchronizedList(new ArrayList<Transaction>());
		}
		list.add(transaction);
		return datastoreService.prepare(query);
	}

	public static Key put(Entity entity) {
		Transaction transaction = datastoreService.beginTransaction();
		List<Transaction> list = activeTransaction.get();
		if (list == null) {
			list = Collections.synchronizedList(new ArrayList<Transaction>());
		}
		list.add(transaction);
		return datastoreService.put(entity);
	}

	public static Future<Key> asyncPut(Entity entity) {
		Future<Transaction> beginTransaction = asyncDatastoreService.beginTransaction();
		List<Future<Transaction>> list = activeAsyncTransaction.get();
		if (list == null) {
				
		}
		list = new ArrayList<Future<Transaction>>();
		return asyncDatastoreService.put(entity);
	}

	public static void asyncPut(Iterable<Entity> entities) {

	}

	public static List<Key> put(Iterable<Entity> entities) {
		Transaction transaction = datastoreService.beginTransaction();
		List<Transaction> list = activeTransaction.get();
		if (list == null) {
			list = Collections.synchronizedList(new ArrayList<Transaction>());
		}
		list.add(transaction);
		return datastoreService.put(entities);
	}

	public static DatastoreAttributes getDatastoreAttributes() {
		Transaction transaction = datastoreService.beginTransaction();
		List<Transaction> list = activeTransaction.get();
		if (list == null) {
			list = Collections.synchronizedList(new ArrayList<Transaction>());
		}
		list.add(transaction);
		return datastoreService.getDatastoreAttributes();
	}

	public static void commit() {
		List<Transaction> list = activeTransaction.get();
		if (list != null) {
			for (Transaction transaction : list) {
				transaction.commit();
			}
		}
	}

	public static void commitAsync() {
		List<Transaction> list = activeTransaction.get();
		if (list != null) {
			for (Transaction transaction : list) {
				transaction.commitAsync();
			}
		}
	}

	public static void rollback() {
		List<Transaction> list = activeTransaction.get();
		if (list != null) {
			for (Transaction transaction : list) {
				transaction.rollback();
			}
		}
	}

	public static void rollbackAsync() {
		List<Transaction> list = activeTransaction.get();
		if (list != null) {
			for (Transaction transaction : list) {
				transaction.rollbackAsync();
			}
		}
	}

}
